package com.cards_game.simple_ddz.verify;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.annotation.Resource;

import com.cards_game.simple_ddz.bean.BaseCardBean;

/**
 * 简单斗地主规则枚举
 * 
 * @author 郭国辉 2016年2月29日 下午5:21:00
 */
public enum SimpleDdzRuleEnum {

	/**
	 * 单牌
	 */
	SINGLE {
		@Override
		public boolean discardCards(List<BaseCardBean> cardBeans) {
			if (cardBeans.size() == 1) {
				return true;
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}

			if (sdv.getWeight(lastCardBeans.get(0).getNum()) < sdv
					.getWeight(thisCardBeans.get(0).getNum())) {
				return true;
			}
			return false;
		}
	},

	/**
	 * 对子
	 */
	PAIR {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			if (simpleDdzBeans.size() == 2) {
				if (simpleDdzBeans.get(0).getNum() == simpleDdzBeans.get(1).getNum()) {
					return true;
				}
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			Set<Integer> lastSet = sdv.getCardsNumList(lastCardBeans);
			Set<Integer> thisSet = sdv.getCardsNumList(thisCardBeans);
			if (lastSet != null && lastSet.size() != 0 && thisSet != null && thisSet.size() != 0) {
				if (lastSet.iterator().next() < thisSet.iterator().next()) {
					return true;
				}
			}
			return false;
		}
	},

	/**
	 * 三个不带
	 */
	THREE {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			if (simpleDdzBeans.size() == 3) {
				Map<Integer, List<BaseCardBean>> map = this.cardingCards(simpleDdzBeans);
				for (Integer num : map.keySet()) {
					if (map.get(num).size() == 3) {
						return true;
					}
				}
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			Set<Integer> lastSet = sdv.getCardsNumList(lastCardBeans);
			Set<Integer> thisSet = sdv.getCardsNumList(thisCardBeans);
			if (lastSet != null && lastSet.size() != 0 && thisSet != null && thisSet.size() != 0) {
				if (lastSet.iterator().next() < thisSet.iterator().next()) {
					return true;
				}
			}
			return false;
		}
	},

	/**
	 * 三带一
	 */
	THREE_ONE {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			if (simpleDdzBeans.size() == 4) {
				Map<Integer, List<BaseCardBean>> map = this.cardingCards(simpleDdzBeans);
				for (Integer num : map.keySet()) {
					if (map.get(num).size() == 3) {
						return true;
					}
				}
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			Map<Integer, List<BaseCardBean>> lastMap = this.cardingCards(lastCardBeans);
			Map<Integer, List<BaseCardBean>> thisMap = this.cardingCards(lastCardBeans);
			int lastNum = -1;
			int thisNum = -1;
			for (Integer num : lastMap.keySet()) {
				if (lastMap.get(num).size() == 3) {
					lastNum = num;
				}
			}
			for (Integer num : thisMap.keySet()) {
				if (thisMap.get(num).size() == 3) {
					thisNum = num;
				}
			}
			if (lastNum != -1 && thisNum != -1) {
				return lastNum < thisNum;
			}
			return false;
		}
	},

	/**
	 * 三带二
	 */
	THREE_TWO {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			boolean three = false;
			boolean two = false;
			if (simpleDdzBeans.size() == 5) {
				Map<Integer, List<BaseCardBean>> map = this.cardingCards(simpleDdzBeans);
				for (Integer num : map.keySet()) {
					if (map.get(num).size() == 3) {
						three = true;
					} else if (map.get(num).size() == 2) {
						two = true;
					}
				}
			}
			return three && two;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			Map<Integer, List<BaseCardBean>> lastMap = this.cardingCards(lastCardBeans);
			Map<Integer, List<BaseCardBean>> thisMap = this.cardingCards(lastCardBeans);
			int lastNum = -1;
			int thisNum = -1;
			for (Integer num : lastMap.keySet()) {
				if (lastMap.get(num).size() == 3) {
					lastNum = num;
				}
			}
			for (Integer num : thisMap.keySet()) {
				if (thisMap.get(num).size() == 3) {
					thisNum = num;
				}
			}
			if (lastNum != -1 && thisNum != -1) {
				return lastNum < thisNum;
			}
			return false;
		}
	},

	/**
	 * 连牌
	 */
	SERIAL {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			Set<Integer> set = sdv.getCardsNumList(simpleDdzBeans);
			if (set.size() >= 5 && set.size() <= 12) {
				return sdv.isSerial(set);
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			Set<Integer> lastSet = sdv.getCardsNumList(lastCardBeans);
			Set<Integer> thisSet = sdv.getCardsNumList(thisCardBeans);
			if (lastSet != null && lastSet.size() != 0 && thisSet != null && thisSet.size() != 0) {
				if (lastSet.iterator().next() < thisSet.iterator().next()) {
					return true;
				}
			}
			return false;
		}
	},

	/**
	 * 连对
	 */
	SHIFTED_PAIRS {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			// 如果出牌张数正确
			if (simpleDdzBeans.size() >= 6 && simpleDdzBeans.size() <= 24) {
				Map<Integer, List<BaseCardBean>> map = this.cardingCards(simpleDdzBeans);
				if (sdv.isSerial(map.keySet())) {
					int count = 2;
					for (Integer tempNum : map.keySet()) {
						int temp = map.get(tempNum).size();
						if (count != temp) {
							count = temp;
							break;
						}
					}
					if (count == 2) {
						return true;
					}
				}
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			Set<Integer> lastSet = sdv.getCardsNumList(lastCardBeans);
			Set<Integer> thisSet = sdv.getCardsNumList(thisCardBeans);
			if (lastSet != null && lastSet.size() != 0 && thisSet != null && thisSet.size() != 0) {
				if (lastSet.iterator().next() < thisSet.iterator().next()) {
					return true;
				}
			}
			return false;
		}
	},

	/**
	 * 残缺的飞机 （不带）
	 */
	INCOMPLETE_AIRCRAFT {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			// 如果出牌张数正确
			if (simpleDdzBeans.size() >= 6 && simpleDdzBeans.size() <= 36) {
				Map<Integer, List<BaseCardBean>> map = this.cardingCards(simpleDdzBeans);
				if (sdv.isSerial(map.keySet())) {
					int count = 3;
					for (Integer tempNum : map.keySet()) {
						int temp = map.get(tempNum).size();
						if (count != temp) {
							count = temp;
							break;
						}
					}
					if (count == 3) {
						return true;
					}
				}
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			Set<Integer> lastSet = sdv.getCardsNumList(lastCardBeans);
			Set<Integer> thisSet = sdv.getCardsNumList(thisCardBeans);
			if (lastSet != null && lastSet.size() != 0 && thisSet != null && thisSet.size() != 0) {
				if (lastSet.iterator().next() < thisSet.iterator().next()) {
					return true;
				}
			}
			return false;
		}
	},

	/**
	 * 飞机
	 */
	AIRCRAFT {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			// 如果出牌张数正确
			if (simpleDdzBeans.size() >= 5 * 2 && simpleDdzBeans.size() <= 5 * 6) {
				Map<Integer, List<BaseCardBean>> map = this.cardingCards(simpleDdzBeans);
				Map<Integer, Map<Integer, List<BaseCardBean>>> map2 = new HashMap<Integer, Map<Integer, List<BaseCardBean>>>();
				for (Integer tempNum : map.keySet()) {
					if (!map2.containsKey(map.get(tempNum).size())) {
						map2.put(map.get(tempNum).size(), new HashMap<Integer, List<BaseCardBean>>());
					}
					Map<Integer, List<BaseCardBean>> tempMap = map2.get(map.get(tempNum).size());
					tempMap.put(tempNum, map.get(tempNum));
					map2.put(map.get(tempNum).size(), tempMap);
				}
				if (map2.size() == 2) {
					if (map2.get(2).size() == map2.get(3).size()) {
						if (sdv.isSerial(map2.get(2).keySet())
								&& sdv.isSerial(map2.get(3).keySet())) {
							return true;
						}
					}
				}
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (lastCardBeans.size() != thisCardBeans.size()) {
				return false;
			}
			if (!discardCards(lastCardBeans)) {
				return false;
			}
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			Map<Integer, List<BaseCardBean>> lastMap = this.cardingCards(lastCardBeans);
			Map<Integer, List<BaseCardBean>> thisMap = this.cardingCards(lastCardBeans);
			int lastNum = -1;
			int thisNum = -1;
			for (Integer num : lastMap.keySet()) {
				if (lastMap.get(num).size() == 3) {
					if (num > lastNum)
						lastNum = num;
				}
			}
			for (Integer num : thisMap.keySet()) {
				if (thisMap.get(num).size() == 3) {
					if (num > thisNum)
						thisNum = num;
				}
			}
			if (lastNum != -1 && thisNum != -1) {
				return lastNum < thisNum;
			}
			return false;
		}
	},

	/**
	 * 炸弹
	 */
	BOMB {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			if (simpleDdzBeans.size() == 4) {
				return sdv.numIsEquivalent(simpleDdzBeans);
			}
			
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			if (!discardCards(thisCardBeans)) {
				return false;
			}
			
			if (KINGS_BOMB.discardCards(lastCardBeans)) {
				return false;
			}else if (discardCards(thisCardBeans)) {
				int lastNum=sdv.getWeight(lastCardBeans.get(0).getNum());
				int thisNum=sdv.getWeight(thisCardBeans.get(0).getNum());
				return thisNum>lastNum;
			}else{
				return true;
			}
		}
	},

	/**
	 * 王炸
	 */
	KINGS_BOMB {
		@Override
		public boolean discardCards(List<BaseCardBean> simpleDdzBeans) {
			if (simpleDdzBeans.size() == 2) {
				return sdv.isKing(simpleDdzBeans);
			}
			return false;
		}

		@Override
		public boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans) {
			return true;
		}
	};
	@Resource
	protected SimpleDdzVerify sdv ;

	/**
	 * 出牌校验
	 * 
	 * @param simpleDdzBeans
	 * @return
	 */
	public abstract boolean discardCards(List<BaseCardBean> simpleDdzBeans);

	/**
	 * 判断出牌是否大于上家
	 * 
	 * @param simpleDdzBeans
	 * @return
	 */
	public abstract boolean canPlayCards(List<BaseCardBean> lastCardBeans, List<BaseCardBean> thisCardBeans);


	/**
	 * 以牌面权值为键，对应纸牌集合为值，梳理纸牌
	 * 
	 * @param simpleDdzBeans
	 * @return
	 */
	protected Map<Integer, List<BaseCardBean>> cardingCards(List<BaseCardBean> baseCardBeans) {
		Map<Integer, List<BaseCardBean>> map = new TreeMap<Integer, List<BaseCardBean>>();
		Set<Integer> set = sdv.getCardsNumList(baseCardBeans);
		for (Integer num : set) {
			List<BaseCardBean> list = new ArrayList<>();
			map.put(num, list);
		}
		for (BaseCardBean bcb : baseCardBeans) {
			map.get(sdv.getWeight(bcb.getNum())).add(bcb);
		}
		return map;
	}
}
